﻿using System.Windows.Controls.Primitives;
using System.Windows.Controls;
using System.Windows.Threading;
using System.Windows;

namespace ThunderboltCustomControlLibrary;

public class CarouselPictureControl:ItemsControl
{
	#region Private Fields

	private const string GridTemplateName = "Part_Grid";
	private const string OldContentControlTemplateName = "Part_OldContentControl";
	private const string NewContentControlTemplateName = "Part_NewContentControl";
	private const string PreButtonTemplateName = "Part_PreButton";
	private const string NextButtonTemplateName = "Part_NextButton";
	private const string StackPanelTemplateName = "Part_StackPanel";

	private DispatcherTimer _timer;
	private Grid _grid;
	private ContentControl _oldContentControl;
	private ContentControl _newContentControl;
	private Button _prevButton;
	private Button _nextButton;
	private StackPanel _stackPanel;
	private int _pageIndex = 0;
	private bool _templateLoaded;
	private bool[] _itemsCheckStatus;
	#endregion
	#region Public Properties

	public TimeSpan Interval
	{
		get => (TimeSpan)GetValue(IntervalProperty);
		set => SetValue(IntervalProperty, value);
	}

	public static readonly DependencyProperty IntervalProperty =
		DependencyProperty.Register(nameof(Interval), typeof(TimeSpan), typeof(CarouselPictureControl), new PropertyMetadata(TimeSpan.FromSeconds(3)));

	public bool IsPauseCarousel
	{
		get => (bool)GetValue(IsPauseCarouselProperty);
		set => SetValue(IsPauseCarouselProperty, value);
	}

	public static readonly DependencyProperty IsPauseCarouselProperty =
		DependencyProperty.Register(nameof(IsPauseCarousel), typeof(bool), typeof(CarouselPictureControl), new PropertyMetadata(false));



	public bool AutoPlay
	{
		get => (bool)GetValue(AutoPlayProperty);
		set => SetValue(AutoPlayProperty, value);
	}

	public static readonly DependencyProperty AutoPlayProperty =
		DependencyProperty.Register(nameof(AutoPlay), typeof(bool), typeof(CarouselPictureControl), new PropertyMetadata(false,
			(o, e) =>
			{
				if (o is CarouselPictureControl d)
				{
					d.TimerSwitch((bool)e.NewValue);
				}
			}));

	public Style PageButtonStyle
	{
		get => (Style)GetValue(PageButtonStyleProperty);
		set => SetValue(PageButtonStyleProperty, value);
	}

	public static readonly DependencyProperty PageButtonStyleProperty =
		DependencyProperty.Register(nameof(PageButtonStyle), typeof(Style), typeof(CarouselPictureControl), new PropertyMetadata(default));

	public int PageIndex
	{
		get => _pageIndex;
		set
		{
			if (Items.Count == 0)
				return;

			if (_pageIndex == value)
				return;

			if (value < 0)
				_pageIndex = Items.Count - 1;
			else if (value >= Items.Count)
				_pageIndex = 0;
			else
				_pageIndex = value;

			SwitchPageButton(_pageIndex);
		}
	}

	#endregion

	#region Events

	public event EventHandler PreButtonClick;
	public event EventHandler NextButtonClick;
	public event EventHandler PageButtonClick;

	#endregion

	#region Constructor

	static CarouselPictureControl()
	{
		DefaultStyleKeyProperty.OverrideMetadata(typeof(CarouselPictureControl), new FrameworkPropertyMetadata(typeof(CarouselPictureControl)));
	}

	public CarouselPictureControl()
	{
		//由于TabCcntrol加载时会加载所有的TabItem,
		//所以进入第一个界面时自定义控件中的Loaded都会执行,
		//而OnApplyTemplate需要你切换TabItem时才会执行,也就导致Loaded在前,
		//OnApplyTemplate在后,感觉是OnApplyTemplate没有执行,
		//手动触发一次OnApplyTemplate
		//OnApplyTemplate();//不适用
		this.Loaded += (d, e) =>
		{
			if (!ApplyTemplate())
			{
				OnApplyTemplate();
			}
			SwitchPageButton(-1);
		}; //也可以直接写在OnApplyTemplate里
	}

	#endregion

	#region Override Methods

	public override void OnApplyTemplate()
	{
		_grid?.RemoveHandler(ButtonBase.ClickEvent, new RoutedEventHandler(ButtonBaseClick));
		_prevButton?.RemoveHandler(ButtonBase.ClickEvent, new RoutedEventHandler(ButtonPreClick));
		_nextButton?.RemoveHandler(ButtonBase.ClickEvent, new RoutedEventHandler(ButtonNextClick));

		base.OnApplyTemplate();

		_templateLoaded = false;
		_grid = GetTemplateChild(GridTemplateName) as Grid;
		_prevButton = GetTemplateChild(PreButtonTemplateName) as Button;
		_nextButton = GetTemplateChild(NextButtonTemplateName) as Button;
		_stackPanel = GetTemplateChild(StackPanelTemplateName) as StackPanel;
		_oldContentControl = GetTemplateChild(OldContentControlTemplateName) as ContentControl;
		_newContentControl = GetTemplateChild(NewContentControlTemplateName) as ContentControl;
		_prevButton?.AddHandler(ButtonBase.ClickEvent, new RoutedEventHandler(ButtonPreClick));
		_nextButton?.AddHandler(ButtonBase.ClickEvent, new RoutedEventHandler(ButtonNextClick));
		_grid?.AddHandler(ButtonBase.ClickEvent, new RoutedEventHandler(ButtonBaseClick));
		//this.Loaded += (d, e) => SwitchPageButton(-1);
		var dic = new ResourceDictionary { Source = new Uri("././Resources/Styles/CarouselPictureControlStyle.xaml", UriKind.Relative) };
		PageButtonStyle = (Style)dic["ToggleButtonMinimalism"];
		_itemsCheckStatus = new bool[Items.Count];
		if (_stackPanel.Children.Count != Items.Count)
		{
			_stackPanel.Children.Clear();
			for (int i = 0; i < Items.Count; i++)
			{
				var btn = new ToggleButton()
				{
					Style = PageButtonStyle
				};
				btn.MouseMove += (s, e) =>
				{
					//鼠标在上方就显示
					if (s is ToggleButton btn)
					{
						_pageIndex = _stackPanel.Children.IndexOf(btn);
						SwitchPageButton(_stackPanel.Children.IndexOf(btn));
					}
					_timer.Stop();
				};
				btn.MouseLeave += (s, e) =>
				{
					IsPauseCarousel = false;
					_timer.Start();
				};
				_stackPanel.Children.Add(btn);
			}
		}
		
		_templateLoaded = true;
	}

	#endregion
	#region Private Methods

	private void TimerSwitch(bool isAutoPlay)
	{
		if (_timer != null)
		{
			_timer.Tick -= _timer_Tick;
			_timer.Stop();
			_timer = null;
		}

		if (!isAutoPlay)
			return;

		_timer = new DispatcherTimer() { Interval = Interval };
		_timer.Tick += _timer_Tick; ;
		_timer.Start();
	}

	private void _timer_Tick(object sender, EventArgs e)
	{
		if (_templateLoaded)
			PageIndex++;
	}

	private async void SwitchPageButton(int index)
	{
		//_stackPanel.Children.Clear();

		if (Items.Count == 0)
			return;

		//for (int i = 0; i < Items.Count; i++)
		//{
		//	_stackPanel.Children.Add(new ToggleButton()
		//	{
		//		Style = PageButtonStyle
		//	});

		//}

		if (index < 0)
			index = Items.Count - 1;

		if (index > Items.Count - 1)
			index = 0;
		
	
		if (_stackPanel.Children[index] is ToggleButton btn)
		{
			btn.IsChecked = true;
			foreach (UIElement stackPanelChild in _stackPanel.Children)
			{
				if (_stackPanel.Children.IndexOf(stackPanelChild) != index)
				{
					if (stackPanelChild is ToggleButton btnElse)
					{
						btnElse.IsChecked = false;
					}
				}
			}
			//btn.RaiseEvent(new RoutedEventArgs(ButtonBase.ClickEvent, btn));
			SwitchPage();
		}
	}

	private void SwitchPage()
	{
		if (Items.Count == 0)
			return;

		if (Items[PageIndex] is FrameworkElement currentElement)
		{
			var oldContent = _newContentControl.Content;
			_newContentControl.Content = null;

			currentElement.Loaded += async (s, e) =>
			{
				var element = s as FrameworkElement;
				await element.SlideAndFadeInAsync(AnimationSlideInDirection.Right, 1.0f);
			};

			currentElement.Unloaded += async (s, e) =>
			{
				var element = s as FrameworkElement;
				await element.SlideAndFadeOutAsync(AnimationSlideInDirection.Left, 1.0f);
			};
			_oldContentControl.Content = oldContent;

			Task.Delay((int)(1 * 1000)).ContinueWith((t) =>
			{
				//回到主线程
				Application.Current.Dispatcher.Invoke(() => _oldContentControl.Content = null);
			});
			_newContentControl.Content = currentElement;
		}
	}

	private void ButtonBaseClick(object sender, RoutedEventArgs e)
	{
		var _selectedButton = e.OriginalSource as RadioButton;

		var index = _stackPanel.Children.IndexOf(_selectedButton);
		if (index != -1)
		{
			PageIndex = index;
		}

		PageButtonClick?.Invoke(sender, e);
	}
	private void ButtonPreClick(object sender, RoutedEventArgs e)
	{
		PageIndex--;
		PreButtonClick?.Invoke(sender, e);
	}

	private void ButtonNextClick(object sender, RoutedEventArgs e)
	{
		PageIndex++;
		NextButtonClick?.Invoke(sender, e);
	}

    #endregion

}
